/**
*   @file
*   PROJETO FINAL DE PROGRAMACAO C  (Prof Fernando. Pacheco)
*
*   JOGO DA VELHA para console / CODIGO EM C
*
*   @author
*   Andre A. Tanaka; Augusto Hoffmann; Felipe Scheidt;
*   Ismael Bonato; Roberto V. Seidler.
*
*
*   Opcoes de jogo: 1 ou 2 jogadores;
*                   possui 2 niveis de dificuldade;
*                   possui jogadas do computador.
*
*   @since 05/12/2011
*
*   RV00 - Entrada de dados e inicializacao - Roberto.
*
*   RV01 - Adicionado movimento CPU - Felipe.
*
*   RV02 - Adicionado verificacao de resultados - Augusto.
*
*   RV03 - Atualizacao da verificacao de resultados - Roberto/Felipe/Tanaka/Augusto.
*
*   RV04 - Saida na tela implementado - Ismael
*
*   RV05 - Opcao de jogar  - Roberto.
*
*   RV06 - Adicionada IA burra - Tanaka.
*
*   RV07 - Estruturacao do codigo - Roberto/Felipe/Tanaka.
*
*   RV08 - Juntar as funcoes - Roberto/Felipe/Tanaka.
*
*   RV09 - Adicionado IA esperta - Roberto/Felipe/Tanaka.
*
*   RV10 - Testes finais.
*
*   @date 15/12/2011
*   @version 1.10
*/


#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>


void inicio (char *players, char *level);
void jogada_player (char players, char *jogada);
void jogada_CPU (char skill,char *jogada,char jogo_atual[9]);
char verifica_resultado (char jogo_atual[9], char players);
void imprime (char jogo_atual[9]);
char ia_burra(void);
char ia_esperta(char tabuleiro[9]);
int y = 0;
int round = 0;


/**
* @brief Funcao Principal.
*/
int main()
{
    char sair;
    do
    {
        char jogadores, dificuldade ='0', resultado = '0', jogadas[10] = {' ',' ',' ',' ',' ',' ',' ',' ',' ','\0'}; /**Inicializacao de variaveis */
        printf("------------JOGO DA VELHA-------------\n");         /**> Imprime na tela o nome do programa */
        inicio (&jogadores,&dificuldade);                           /**> chama funcao de inicializacao */
        round = 0;
        while (1)                                                   /**> enquanto nao houver resultado executa o laco */
        {
            jogada_player(jogadores,jogadas);                       /**> Chama funcao de jogadas feitas por players humanos */
            imprime (jogadas);                                      /**> Imprime na tela o jogo atual */
            resultado = verifica_resultado (jogadas,jogadores);     /**> Chama funcao de verificacao de resultados */
            if (resultado == '1') break;                            /**> Se houver resultado encerra o laco */
            if (jogadores=='1')
            {
                jogada_CPU(dificuldade, jogadas, jogadas);           /**> Se houver somente 1 jogador chama funcao de jogada da Intelegencia artificial */
                imprime (jogadas);                                   /**> Imprime na tela o jogo atual */
                resultado = verifica_resultado (jogadas, jogadores); /**> chama funcao de verificacao de resultados */
                if (resultado == '1') break;                         /**> Se houver resultado encerra o laco */
            }
        }
        printf("\n\nPressione qualquer tecla para jogar\nnovamente ou [s] para sair.\n\n"); /**> Pegunta ao jogador se deseja jogar novamente */
        fflush(stdin);                                                /**> Limpa Buffer do teclado */
        sair=getch();
    }
    while (sair!='s');  /**> Se desejar sair o programa eh encerrado */
    return 0;
}


/**
* @brief Funcao de inicializacao.
* @param players char que representa o numero de jogadores.
* @param level representa o nivel de dificuldade f ou d.
* @see main().
*/
void inicio (char *players, char *level)
{
    char temp; /**> Inicializa variavel temporaria */
    while (1)
    {
        printf("\nDigite o numero de jogadores:");    /**> Seleciona jogo contra a CPU ou VS outro player */
        fflush(stdin);
        scanf("%c",&temp);
        if (temp != '1' && temp != '2')               /**> Se diferente de 1 ou 2 mostra opcao invalida */
        {                                             /**> e recomeca o laco */
            printf("Opcao Invalida!!");
        }
        else
        {
            *players = temp;                          /**> Caso contrario contunua */
            break;
        }
    }
    if (temp == '1')                                  /**> Se for escolhido opcao de 1 jogador entra no laco de selecao de dificuldades */
    {
        while(1)
        {
            printf("\nDigite a dificuldade do oponente: \n[f] = facil \n[d] = dificil:");   /**> Pregunta ao jogador o nivel de habilidade da Inteligencia Artificial */
            fflush(stdin);
            scanf("%c",&temp);
            if (temp != 'd' && temp != 'f')           /**> Se a opcao digitada for diferente de 'f' ou 'd' mostra opcao invalida e refaz a pergunta */

            {
                printf("Opcao Invalida!!\n");
            }
            else break;                               /**> Caso contrario sai do laco */
        }
        *level = temp;
    }
    printf("\nO tabuleiro segue o seguinte padrao:\n\n");       /**> Informa ao jogador como cada opcao de jogada ira ser apresentada na tela */
    printf(" 1 | 2 | 3 \n");
    printf("---+---+---\n");
    printf(" 4 | 5 | 6 \n");
    printf("---+---+---\n");
    printf(" 7 | 8 | 9 \n\n");
}


/**
* @brief Funcao que faz jogadas dos jogadores.
* @param players char que representa o numero de jogadores.
* @param jogada ponteiro para o vetor char.
* @see jogada_CPU(), main().
*/
void jogada_player (char players, char *jogada)
{
#define player1 'X'
#define player2 'O'                                              /**> Define o simbolo de cada jogador */
    int posicao;
    while(1)
    {
        printf("Digite sua jogada:");                           /**> Informa o jogador que o programa aguarda sua jogada */
        fflush(stdin);                                          /**> Limpa buffer do teclado */
        posicao=getch();                                        /**> Captura movimento */
        posicao=posicao-0x30;
        if ((posicao < 1) || (posicao > 9))                     /**> Se a opcao digitada for diferente das posicoes do tabuleiro mostra mensagem de erro */
        {                                                       /**> aguarda novamente uma jogada */
            printf("Jogada Invalida\n");
        }
        else if(jogada[posicao-1]!=' ')                         /**> Compara movimento para verificar se eh valido, se nao for aguarda por um movimento valido */
        {
            printf("Movimento ja realizado!\n");
        }
        else
        {
            if (players =='2')
            {
                if(y==0)
                    jogada[posicao-1]=player1;
                else                                            /**> Se valido o movimento, joga  mesmo no vetor o simbolo do jogador correspondente e sai do laco */
                    jogada[posicao-1]=player2;
                y=~y;
            }
            else
            {
                jogada[posicao-1]=player1;
            }
            break;
        }
    }
}


/**
* @brief Funcao que faz as jogadas do Computador.
* @param skill char que representa o nivel de dificuldade.
* @param jogada aponta para o vetor de posicao.
* @param jogo_atual vetor armazena as jogadas atuais.
* @see main()
*/
void jogada_CPU (char skill, char *jogada, char jogo_atual[9])
{
    char posicao = '0';                                         /**> Variavel para armazenar a jogada da CPU */
    while (1)
    {
        if (skill=='f')
        {
            posicao=ia_burra();                                 /**> Se foi selecionada a dificuldade facil chama a IA facil */
        }
        else
        {
            posicao=ia_esperta(jogo_atual);                     /**> Caso contrario chama a IA dificil */
        }
        if(jogada[posicao-0]!=' ') continue;                    /**> Verifica se o movimento eh valido, se nao for retorna ao comeco do laco */
        else
        {
            jogada[posicao-0]= 'O';                             /**> Se for valido sai do laco */
            break;
        }
    }
}


/**
* @brief Funcao IA burra para o nivel facil.
* Gera um numero 'x' aleatorio de 0 a 8.
* @return numero aleatorio x.
* @see main().
*/
char ia_burra(void)
{
    char x;
    srand(time(NULL)); /**> Gera um aleatorio */
    x = rand()%8;
    return(x);
}


/**
* @brief Funcao que Verifica os resultados.
* @param jogo_atual vetor de char que representa o jogo atual.
* @param players representa numero de jogadores.
* @return indicacao de fim do jogo para o restante do programa.
* @see main()
*/
char verifica_resultado (char jogo_atual[9], char players)
{
    char fim = '0';
    if(	    jogo_atual[0] == 'X' && jogo_atual[1] == 'X' && jogo_atual[2] == 'X' || /**> Verifica todas as possibilidades de vitoria de 'X' */
            jogo_atual[3] == 'X' && jogo_atual[4] == 'X' && jogo_atual[5] == 'X' ||
            jogo_atual[6] == 'X' && jogo_atual[7] == 'X' && jogo_atual[8] == 'X' ||

            jogo_atual[0] == 'X' && jogo_atual[3] == 'X' && jogo_atual[6] == 'X' ||
            jogo_atual[1] == 'X' && jogo_atual[4] == 'X' && jogo_atual[7] == 'X' ||
            jogo_atual[2] == 'X' && jogo_atual[5] == 'X' && jogo_atual[8] == 'X' ||

            jogo_atual[0] == 'X' && jogo_atual[4] == 'X' && jogo_atual[8] == 'X' ||
            jogo_atual[2] == 'X' && jogo_atual[4] == 'X' && jogo_atual[6] == 'X')
    {
        if (players=='1')
        {
            printf ("\n\nVoce ganhou!\n\n");
            fim++;
        }
        else                                                    /**> Se vitoria confirmada imprime na tela uma mensagem */
        {
            printf ("\n\nPlayer 1 ganhou!\n\n");
            fim++;
        }
    }

    else if(jogo_atual[0] == 'O' && jogo_atual[1] == 'O' && jogo_atual[2] == 'O' || /**> verifica todas as possibilidades de vitoria do "O" */
            jogo_atual[3] == 'O' && jogo_atual[4] == 'O' && jogo_atual[5] == 'O' ||
            jogo_atual[6] == 'O' && jogo_atual[7] == 'O' && jogo_atual[8] == 'O' ||

            jogo_atual[0] == 'O' && jogo_atual[3] == 'O' && jogo_atual[6] == 'O' ||
            jogo_atual[1] == 'O' && jogo_atual[4] == 'O' && jogo_atual[7] == 'O' ||
            jogo_atual[2] == 'O' && jogo_atual[5] == 'O' && jogo_atual[8] == 'O' ||

            jogo_atual[0] == 'O' && jogo_atual[4] == 'O' && jogo_atual[8] == 'O' ||
            jogo_atual[2] == 'O' && jogo_atual[4] == 'O' && jogo_atual[6] == 'O')
    {
        if (players=='1')
        {
            printf("\n\nVoce perdeu, looser!\n\n");
            fim++;
        }
        else                                                    /**> Se vitoria confirmada imprime na tela uma mensagem */
        {
            printf ("\n\nPlayer 2 ganhou!\n\n");
            fim++;
        }
    }

    else if(jogo_atual[0] != ' ' && jogo_atual[1] != ' ' && jogo_atual[2] != ' ' && /**> Se todas as posicoes forem preenchidas e nao houver vencedor, eh declarado empate */
            jogo_atual[3] != ' ' && jogo_atual[4] != ' ' && jogo_atual[5] != ' ' &&
            jogo_atual[6] != ' ' && jogo_atual[7] != ' ' && jogo_atual[8] != ' ')
    {
        printf("\n\nDeu Velhaaa!\n\n");
        fim++;
    }
    return (fim);
}


/**
* @brief Funcao que Imprime o Tabuleiro.
* @param jogo_atual vetor de char que representa o jogo atual.
* @see main()
*/
void imprime (char jogo_atual[9])
{
    system("cls");  /**> Limpa a tela */
    printf(" %c | %c | %c \n",jogo_atual[0],jogo_atual[1],jogo_atual[2]);
    printf("---+---+---\n");
    printf(" %c | %c | %c \n",jogo_atual[3],jogo_atual[4],jogo_atual[5]); /**> Motra na tela a situacao atual do jogo */
    printf("---+---+---\n");
    printf(" %c | %c | %c \n",jogo_atual[6],jogo_atual[7],jogo_atual[8]);
}

/**
* @brief Funcao IA esperta.
* @param tabuleiro vetor de char que representa a posicao no vetor.
* @return jogada da IA esperta.
* @see main()
*/
char ia_esperta(char tabuleiro[9])
{
    int retorno=0;      /**> Inicializa variaveis de retorno */
    char indice;
    if (round > 0)
    {
        retorno = ia_burra();       /**> Se nao houver nenhum ateque ou defesa para serem realizados faz uma jogada aleatoria */
    }

    if (round == 0)
    {
        if ((tabuleiro[0]=='X') ||(tabuleiro[2]=='X') ||(tabuleiro[6]=='X') || (tabuleiro[8]=='X'))
        {
            retorno = 4;                /**> Se o primeiro movimento do jogador for em um dos cantos a CPU devera jogar no meio */
            round++;
        }
        else if (tabuleiro[4]=='X')
        {
            while(1)
            {
                retorno = ia_burra();
                if ((retorno!= 0) && (retorno!= 2) && (retorno!= 6) && (retorno!= 8)) continue;
                else
                {
                    round++;            /**> Se o primeiro movimento do jogador for no meio a CPU devera jogar nos cantos */
                    break;
                }

            }
        }
        else
        {
            retorno = ia_burra();       /**> Nao havendo jogadas no meio ou cantos faz uma jogada aleatoria */
            round++;
        }
    }

    /**> Verifica as posibilidades de ganhar do usuario escaneando o tabuleiro e a posicao no vetor de jogadas*/

    /**> Faz movimentos de defesa */
    if(tabuleiro[0]=='X' && tabuleiro[4]=='X')
        if(tabuleiro[8]==' ')
        {
            retorno =8;
        }
    if(tabuleiro[0]=='X' && tabuleiro[8]=='X')
        if(tabuleiro[4]==' ')
        {
            retorno =4;
        }
    if(tabuleiro[4]=='X' && tabuleiro[8]=='X')
        if(tabuleiro[0]==' ')
        {
            retorno =0;
        }

    if(tabuleiro[2]=='X' && tabuleiro[4]=='X')
        if(tabuleiro[6]==' ')
        {
            retorno =6;
        }
    if(tabuleiro[2]=='X' && tabuleiro[6]=='X')
        if(tabuleiro[4]==' ')
        {
            retorno =4;
        }
    if(tabuleiro[6]=='X' && tabuleiro[4]=='X')
        if(tabuleiro[2]==' ')
        {
            retorno =2;
        }

    if(tabuleiro[0]=='X' && tabuleiro[1]=='X')
        if(tabuleiro[2]==' ')
        {
            retorno =2;
        }
    if(tabuleiro[1]=='X' && tabuleiro[2]=='X')
        if(tabuleiro[0]==' ')
        {
            retorno =0;
        }
    if(tabuleiro[0]=='X' && tabuleiro[2]=='X')
        if(tabuleiro[1]==' ')
        {
            retorno =1;
        }

    if(tabuleiro[3]=='X' && tabuleiro[4]=='X')
        if(tabuleiro[5]==' ')
        {
            retorno =5;
        }
    if(tabuleiro[4]=='X' && tabuleiro[5]=='X')
        if(tabuleiro[3]==' ')
        {
            retorno =3;
        }
    if(tabuleiro[3]=='X' && tabuleiro[5]=='X')
        if(tabuleiro[4]==' ')
        {
            retorno =4;
        }

    if(tabuleiro[6]=='X' && tabuleiro[7]=='X')
        if(tabuleiro[8]==' ')
        {
            retorno =8;
        }
    if(tabuleiro[6]=='X' && tabuleiro[8]=='X')
        if(tabuleiro[7]==' ')
        {
            retorno =7;
        }
    if(tabuleiro[7]=='X' && tabuleiro[8]=='X')
        if(tabuleiro[6]==' ')
        {
            retorno =6;
        }

    if(tabuleiro[0]=='X' && tabuleiro[3]=='X')
        if(tabuleiro[6]==' ')
        {
            retorno =6;
        }
    if(tabuleiro[3]=='X' && tabuleiro[6]=='X')
        if(tabuleiro[0]==' ')
        {
            retorno =0;
        }
    if(tabuleiro[0]=='X' && tabuleiro[6]=='X')
        if(tabuleiro[3]==' ')
        {
            retorno =3;
        }


    if(tabuleiro[1]=='X' && tabuleiro[4]=='X')
        if(tabuleiro[7]==' ')
        {
            retorno =7;
        }
    if(tabuleiro[4]=='X' && tabuleiro[7]=='X')
        if(tabuleiro[1]==' ')
        {
            retorno =1;
        }
    if(tabuleiro[1]=='X' && tabuleiro[7]=='X')
        if(tabuleiro[4]==' ')
        {
            retorno =4;
        }


    if(tabuleiro[2]=='X' && tabuleiro[5]=='X')
        if(tabuleiro[8]==' ')
        {
            retorno =8;
        }
    if(tabuleiro[2]=='X' && tabuleiro[8]=='X')
        if(tabuleiro[5]==' ')
        {
            retorno =5;
        }
    if(tabuleiro[5]=='X' && tabuleiro[8]=='X')
        if(tabuleiro[2]==' ')
        {
            retorno =2;
        }

    if(tabuleiro[0]=='O' && tabuleiro[4]=='O')
        if(tabuleiro[8]==' ')
        {
            retorno ='8';
        }

    /**> Faz movimentos de Ataque */
    if(tabuleiro[0]=='O' && tabuleiro[8]=='O')
        if(tabuleiro[4]==' ')
        {
            retorno =4;
        }
    if(tabuleiro[4]=='O' && tabuleiro[8]=='O')
        if(tabuleiro[0]==' ')
        {
            retorno =0;
        }

    if(tabuleiro[2]=='O' && tabuleiro[4]=='O')
        if(tabuleiro[6]==' ')
        {
            retorno =6;
        }
    if(tabuleiro[2]=='O' && tabuleiro[6]=='O')
        if(tabuleiro[4]==' ')
        {
            retorno =4;
        }
    if(tabuleiro[6]=='O' && tabuleiro[4]=='O')
        if(tabuleiro[2]==' ')
        {
            retorno =2;
        }


    if(tabuleiro[0]=='O' && tabuleiro[1]=='O')
        if(tabuleiro[2]==' ')
        {
            retorno =2;
        }
    if(tabuleiro[1]=='O' && tabuleiro[2]=='O')
        if(tabuleiro[0]==' ')
        {
            retorno =0;
        }
    if(tabuleiro[0]=='O' && tabuleiro[2]=='O')
        if(tabuleiro[1]==' ')
        {
            retorno =1;
        }

    if(tabuleiro[3]=='O' && tabuleiro[4]=='O')
        if(tabuleiro[5]==' ')
        {
            retorno =5;
        }
    if(tabuleiro[4]=='O' && tabuleiro[5]=='O')
        if(tabuleiro[3]==' ')
        {
            retorno =3;
        }
    if(tabuleiro[3]=='O' && tabuleiro[5]=='O')
        if(tabuleiro[4]==' ')
        {
            retorno =4;
        }

    if(tabuleiro[6]=='O' && tabuleiro[7]=='O')
        if(tabuleiro[8]==' ')
        {
            retorno =8;
        }
    if(tabuleiro[6]=='O' && tabuleiro[8]=='O')
        if(tabuleiro[7]==' ')
        {
            retorno =7;
        }
        else if(tabuleiro[7]=='O' && tabuleiro[8]=='O')
            if(tabuleiro[6]==' ')
            {
                retorno =6;
            }

    if(tabuleiro[0]=='O' && tabuleiro[3]=='O')
        if(tabuleiro[6]==' ')
        {
            retorno =6;
        }
    if(tabuleiro[3]=='O' && tabuleiro[6]=='O')
        if(tabuleiro[0]==' ')
        {
            retorno =0;
        }
    if(tabuleiro[0]=='O' && tabuleiro[6]=='O')
        if(tabuleiro[3]==' ')
        {
            retorno =3;
        }


    if(tabuleiro[1]=='O' && tabuleiro[4]=='O')
        if(tabuleiro[7]==' ')
        {
            retorno =7;
        }
    if(tabuleiro[4]=='O' && tabuleiro[7]=='O')
        if(tabuleiro[1]==' ')
        {
            retorno =1;
        }
    if(tabuleiro[1]=='O' && tabuleiro[7]=='O')
        if(tabuleiro[4]==' ')
        {
            retorno =4;
        }


    if(tabuleiro[2]=='O' && tabuleiro[5]=='O')
        if(tabuleiro[8]==' ')
        {
            retorno =8;
        }
    if(tabuleiro[2]=='O' && tabuleiro[8]=='O')
        if(tabuleiro[5]==' ')
        {
            retorno =5;
        }
    if(tabuleiro[5]=='O' && tabuleiro[8]=='O')
        if(tabuleiro[2]==' ')
        {
            retorno =2;
        }

    itoa(retorno,&indice,10);
    indice=indice-48;           /**> Adequa as variaveis para serem utilizadas no restante do programa */
    return(indice);
}
